import pathlib
import pickle

from win32gui import *
import cv2
import win32con
import win32gui
import win32print
import ctypes
import sys

import arrow

"""添加多级导入的模块路径"""
path = pathlib.Path(".")
sys.path.append("entity")
ddt_path = str(path.absolute())
dsft_path = str(path.absolute().parent.absolute())
sys.path.extend([
    ddt_path,
    dsft_path
])


class Window:
    def __init__(self):
        self.window = None
        self.title = ""
        self.screen_width = get_real_resolution()[0]
        self.screen_height = get_real_resolution()[1]
        self.WIDTH = int(get_real_resolution()[0] * 0.8)
        self.HEIGHT = int(get_real_resolution()[1] * 0.8)

    def set_function(self):
        pass

    def hide(self):
        # 窗口最小化
        self.window.state("iconic")
        # 窗口不可见
        self.window.wm_attributes("-alpha", 0)

    def show(self):
        # 窗口正常
        self.window.state("normal")
        # 窗口可见
        self.window.wm_attributes("-alpha", 1)

    def set_window(self):
        """设置窗口属性"""
        # 默认窗口包含标题栏
        self.window.overrideredirect(False)
        # 初始化窗口大小并自适应屏幕
        self.window.geometry(f"+{int((self.screen_width - self.WIDTH) // 3)}+"
                             f"{int((self.screen_height - self.HEIGHT) // 3)}")
        if not (self.WIDTH == 0 and self.HEIGHT == 0):
            self.window.geometry(f"{self.WIDTH}x{self.HEIGHT}+"
                                 f"{(self.screen_width - self.WIDTH) // 2}+"
                                 f"{((self.screen_height - self.HEIGHT) // 2) - 50}")
        # 设置标题
        self.window.title(self.title)
        # 设置图标
        self.window.iconbitmap("images/logo.ico")
        # 调用api设置成由应用程序缩放
        ctypes.windll.shcore.SetProcessDpiAwareness(1)
        # 调用api获得当前的缩放因子
        scale_factor = ctypes.windll.shcore.GetScaleFactorForDevice(0)
        self.window.tk.call("tk", "scaling", scale_factor / 75)
        # 设置功能
        self.set_function()


def get_real_resolution():
    """获取真实的分辨率"""
    hDC = win32gui.GetDC(0)
    # 横向分辨率
    w = win32print.GetDeviceCaps(hDC, win32con.DESKTOPHORZRES)
    # 纵向分辨率
    h = win32print.GetDeviceCaps(hDC, win32con.DESKTOPVERTRES)
    return w, h


def is_number(s):
    """判断是否时数字"""
    try:
        float(s)
        return True
    except ValueError:
        pass

    try:
        import unicodedata
        unicodedata.numeric(s)
        return True
    except (TypeError, ValueError):
        pass
    return False


def cv2_read(path):
    """读取图片为cv2"""
    return gray(cv2.imread(path))


def gray(cv2_image):
    """灰度识别"""
    return cv2.cvtColor(cv2_image, cv2.COLOR_BGR2GRAY)


def image_to_position(screen, template):
    """抓图返回坐标和识别率"""
    image_x, image_y = template.shape[:2]
    result = cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    result_list = [max_val, max_loc, image_x, image_y]
    return result_list


def dir_empty(dir_path):
    """判断文件夹是否为空"""
    has_next = next(dir_path.iterdir(), None)
    if has_next is None:
        return True
    return False


def rm_tree(pth):
    """删除目录下所有文件"""
    for child in pth.glob('*'):
        if child.is_file():
            child.unlink()
        else:
            rm_tree(child)
    pth.rmdir()


def get_time():
    """获取当前时间"""
    now = arrow.now()
    return now


def get_time_to_log():
    """获取当前时间并且日志格式化"""
    now = arrow.now()
    return f"{now.year}年{now.month}月{now.day}日 " \
           f"{now.hour}:{now.minute}:{now.second}\t"


def get_del_line(text_tk):
    text_list = text_tk.get("1.0", "end").split("\n")
    if "按<Tab>键继续..." in text_list:
        return str(text_list.index("按<Tab>键继续...") + 1) + ".0"
    return "end"


def image_to_project(image):
    """将image信息保存至项目"""
    project_name = add_encode_information(image.project_name, "__ProjectName__")
    scene = add_encode_information(image.scene, "__Scene__")
    desc = add_encode_information(image.desc, "__Desc__")
    threshold = add_encode_information(image.threshold, "__Threshold__")
    operation = add_encode_information(image.operation, "__Operation__")
    # 图片信息
    image_information = "__Information__".encode() \
                        + project_name \
                        + scene \
                        + desc \
                        + threshold \
                        + operation \
                        + "__Information__".encode()
    image_to_file(image.path, image_information)
    return True


def image_to_file(path, information):
    """图片信息保存至文件"""
    with open(path, "a+b") as f:
        if type(information) is bytes:
            f.write(information)


def add_encode_information(value, information):
    """把value包装起来以载入图片"""
    if type(value) == list:
        return information.encode() + pickle.dumps(value) + information.encode()
    return information.encode() + value.encode() + information.encode()


def get_apps():
    """获取应用程序进程列表"""
    list_lpWindowName = []
    titles = set()

    def foo(hwnd, nouse):
        # 去掉下面这句就所有都输出了，但是我不需要那么多
        if IsWindow(hwnd) and IsWindowEnabled(hwnd) and IsWindowVisible(hwnd):
            titles.add(GetWindowText(hwnd))

    EnumWindows(foo, 0)
    lt = [t for t in titles if t]
    lt.sort()
    for t in lt:
        list_lpWindowName.append(t)
    return list_lpWindowName


def send_message(conn, message):
    conn.send(message)


def get_message(conn):
    return conn.recv()